import fs from 'fs/promises';
import path from 'path';
import yaml from 'yaml';
import { createHash } from 'crypto';

export default {
  name: 'data-editor',
  description: '高级数据编辑管理API - 支持JSON/YAML/XML文件操作',

  routes: [
    // ========== 文件读取 API ==========
    {
      method: 'GET',
      path: '/api/data/read',
      handler: async (req, res, Bot) => {
        if (!Bot.checkApiAuthorization(req)) {
          return res.status(403).json({ success: false, message: 'Unauthorized' });
        }

        try {
          const { 
            filePath, 
            encoding = 'utf8',
            includeMetadata = true,
            validateJson = true 
          } = req.query;
          
          if (!filePath) {
            return res.status(400).json({ 
              success: false, 
              message: '缺少文件路径参数' 
            });
          }

          // 安全路径验证
          const { isValid, normalizedPath, error } = validateFilePath(filePath);
          if (!isValid) {
            return res.status(403).json({ success: false, message: error });
          }

          // 检查文件是否存在
          try {
            await fs.access(normalizedPath, fs.constants.R_OK);
          } catch {
            return res.status(404).json({ 
              success: false, 
              message: '文件不存在或无读取权限' 
            });
          }

          // 读取文件内容
          const content = await fs.readFile(normalizedPath, encoding);
          const ext = path.extname(normalizedPath).toLowerCase();
          
          const parseResult = parseFileContent(content, ext, validateJson);
          
          if (!parseResult.success) {
            return res.status(400).json({
              success: false,
              message: '文件解析失败',
              error: parseResult.error
            });
          }
          
          // 获取文件元数据
          let metadata = {};
          if (includeMetadata) {
            const stats = await fs.stat(normalizedPath);
            metadata = {
              path: normalizedPath,
              type: parseResult.fileType,
              size: stats.size,
              modified: stats.mtime,
              created: stats.birthtime,
              extension: ext,
              encoding,
              checksum: createHash('md5').update(content).digest('hex')
            };
          }
          
          res.json({ 
            success: true, 
            data: parseResult.data,
            metadata
          });

        } catch (error) {
          logger.error('[Data Editor API] 文件读取失败', error);
          res.status(500).json({ 
            success: false, 
            message: '文件读取失败',
            error: error.message 
          });
        }
      }
    },

    // ========== 文件写入 API ==========
    {
      method: 'POST',
      path: '/api/data/write',
      handler: async (req, res, Bot) => {
        if (!Bot.checkApiAuthorization(req)) {
          return res.status(403).json({ success: false, message: 'Unauthorized' });
        }

        try {
          const { 
            filePath, 
            data, 
            format,
            operation = 'overwrite',
            createIfNotExist = true,
            backup = true,
            encoding = 'utf8',
            options = {},
            validation = true,
            atomic = true
          } = req.body;

          // 参数验证
          const validationResult = validateWriteParams(filePath, data, operation);
          if (!validationResult.success) {
            return res.status(400).json(validationResult);
          }

          const { isValid, normalizedPath, error } = validateFilePath(filePath);
          if (!isValid) {
            return res.status(403).json({ success: false, message: error });
          }

          // 确定文件格式
          const ext = path.extname(normalizedPath).toLowerCase();
          const fileFormat = determineFileFormat(format, ext);

          // 检查文件是否存在
          const fileExists = await checkFileExists(normalizedPath);
          
          if (!fileExists && !createIfNotExist) {
            return res.status(404).json({ 
              success: false, 
              message: '文件不存在且不允许创建' 
            });
          }

          let finalData = data;
          let backupPath = null;

          // 根据操作类型处理数据
          if (fileExists && operation !== 'overwrite') {
            const processResult = await processFileOperation(
              normalizedPath, 
              data, 
              operation, 
              fileFormat, 
              encoding,
              req.body.path
            );
            
            if (!processResult.success) {
              return res.status(400).json(processResult);
            }
            
            finalData = processResult.data;
          }

          // 数据验证
          if (validation) {
            const validateResult = validateData(finalData, fileFormat);
            if (!validateResult.success) {
              return res.status(400).json(validateResult);
            }
          }

          // 创建备份
          if (backup && fileExists) {
            backupPath = await createBackup(normalizedPath);
          }

          // 确保目录存在
          const dir = path.dirname(normalizedPath);
          await fs.mkdir(dir, { recursive: true });

          // 格式化内容
          const content = formatContent(finalData, fileFormat, options);
          
          // 原子写入
          if (atomic) {
            await atomicWrite(normalizedPath, content, encoding);
          } else {
            await fs.writeFile(normalizedPath, content, encoding);
          }

          // 验证写入结果
          const stats = await fs.stat(normalizedPath);

          res.json({ 
            success: true, 
            message: `${fileFormat.toUpperCase()}文件写入成功`,
            metadata: {
              path: normalizedPath,
              format: fileFormat,
              operation,
              backup: backupPath,
              size: stats.size,
              checksum: createHash('md5').update(content).digest('hex')
            }
          });

        } catch (error) {
          logger.error('[Data Editor API] 文件写入失败', error);
          res.status(500).json({ 
            success: false, 
            message: '文件写入失败',
            error: error.message 
          });
        }
      }
    },

    // ========== 文件列表 API ==========
    {
      method: 'GET',
      path: '/api/data/list',
      handler: async (req, res, Bot) => {
        if (!Bot.checkApiAuthorization(req)) {
          return res.status(403).json({ success: false, message: 'Unauthorized' });
        }

        try {
          const { 
            dirPath = '.', 
            filter,
            recursive = false,
            includeMetadata = false 
          } = req.query;

          const { isValid, normalizedPath, error } = validateFilePath(dirPath);
          if (!isValid) {
            return res.status(403).json({ success: false, message: error });
          }

          const files = await listFiles(normalizedPath, filter, recursive, includeMetadata);
          
          res.json({ 
            success: true, 
            data: files,
            metadata: {
              directory: normalizedPath,
              count: files.length,
              recursive
            }
          });

        } catch (error) {
          logger.error('[Data Editor API] 文件列表获取失败', error);
          res.status(500).json({ 
            success: false, 
            message: '文件列表获取失败',
            error: error.message 
          });
        }
      }
    },

    // ========== 文件删除 API ==========
    {
      method: 'DELETE',
      path: '/api/data/delete',
      handler: async (req, res, Bot) => {
        if (!Bot.checkApiAuthorization(req)) {
          return res.status(403).json({ success: false, message: 'Unauthorized' });
        }

        try {
          const { filePath, backup = true } = req.body;

          if (!filePath) {
            return res.status(400).json({ 
              success: false, 
              message: '缺少文件路径参数' 
            });
          }

          const { isValid, normalizedPath, error } = validateFilePath(filePath);
          if (!isValid) {
            return res.status(403).json({ success: false, message: error });
          }

          const fileExists = await checkFileExists(normalizedPath);
          if (!fileExists) {
            return res.status(404).json({ 
              success: false, 
              message: '文件不存在' 
            });
          }

          let backupPath = null;
          if (backup) {
            backupPath = await createBackup(normalizedPath);
          }

          await fs.unlink(normalizedPath);

          res.json({ 
            success: true, 
            message: '文件删除成功',
            metadata: {
              path: normalizedPath,
              backup: backupPath
            }
          });

        } catch (error) {
          logger.error('[Data Editor API] 文件删除失败', error);
          res.status(500).json({ 
            success: false, 
            message: '文件删除失败',
            error: error.message 
          });
        }
      }
    },

    // ========== 文件复制/移动 API ==========
    {
      method: 'POST',
      path: '/api/data/copy',
      handler: async (req, res, Bot) => {
        if (!Bot.checkApiAuthorization(req)) {
          return res.status(403).json({ success: false, message: 'Unauthorized' });
        }

        try {
          const { sourcePath, targetPath, move = false, overwrite = false } = req.body;

          if (!sourcePath || !targetPath) {
            return res.status(400).json({ 
              success: false, 
              message: '缺少源路径或目标路径参数' 
            });
          }

          const sourceValidation = validateFilePath(sourcePath);
          const targetValidation = validateFilePath(targetPath);
          
          if (!sourceValidation.isValid) {
            return res.status(403).json({ success: false, message: `源路径错误: ${sourceValidation.error}` });
          }
          
          if (!targetValidation.isValid) {
            return res.status(403).json({ success: false, message: `目标路径错误: ${targetValidation.error}` });
          }

          const sourceExists = await checkFileExists(sourceValidation.normalizedPath);
          if (!sourceExists) {
            return res.status(404).json({ 
              success: false, 
              message: '源文件不存在' 
            });
          }

          const targetExists = await checkFileExists(targetValidation.normalizedPath);
          if (targetExists && !overwrite) {
            return res.status(409).json({ 
              success: false, 
              message: '目标文件已存在' 
            });
          }

          // 确保目标目录存在
          const targetDir = path.dirname(targetValidation.normalizedPath);
          await fs.mkdir(targetDir, { recursive: true });

          if (move) {
            await fs.rename(sourceValidation.normalizedPath, targetValidation.normalizedPath);
          } else {
            await fs.copyFile(sourceValidation.normalizedPath, targetValidation.normalizedPath);
          }

          const stats = await fs.stat(targetValidation.normalizedPath);

          res.json({ 
            success: true, 
            message: `文件${move ? '移动' : '复制'}成功`,
            metadata: {
              source: sourceValidation.normalizedPath,
              target: targetValidation.normalizedPath,
              operation: move ? 'move' : 'copy',
              size: stats.size
            }
          });

        } catch (error) {
          logger.error('[Data Editor API] 文件复制/移动失败', error);
          res.status(500).json({ 
            success: false, 
            message: `文件${req.body.move ? '移动' : '复制'}失败`,
            error: error.message 
          });
        }
      }
    }
  ],

  // 初始化函数
  init: (app, bot) => {
    logger.info('[Data Editor API] 高级数据编辑API已加载');
    logger.info('[Data Editor API] 支持功能：JSON/YAML/XML 文件完整操作');
    logger.info('[Data Editor API] 可用端点：read, write, list, delete, copy');
  }
};

// ========== 辅助函数 ==========

/**
 * 验证文件路径安全性
 */
function validateFilePath(filePath) {
  if (!filePath || typeof filePath !== 'string') {
    return { isValid: false, error: '无效的文件路径' };
  }

  const normalizedPath = path.normalize(filePath);
  
  // 检查路径遍历攻击
  if (normalizedPath.includes('..') || normalizedPath.startsWith('/etc') || 
      normalizedPath.startsWith('/proc') || normalizedPath.startsWith('/sys')) {
    return { isValid: false, error: '非法路径访问' };
  }

  // 检查敏感文件
  const sensitivePatterns = [
    /passwd$/,
    /shadow$/,
    /\.ssh/,
    /\.env$/,
    /config\.json$/
  ];

  if (sensitivePatterns.some(pattern => pattern.test(normalizedPath))) {
    return { isValid: false, error: '禁止访问敏感文件' };
  }

  return { isValid: true, normalizedPath };
}

/**
 * 解析文件内容
 */
function parseFileContent(content, ext, validateJson = true) {
  try {
    let data;
    let fileType;

    if (ext === '.json') {
      data = JSON.parse(content);
      fileType = 'json';
    } else if (['.yml', '.yaml'].includes(ext)) {
      data = yaml.parse(content);
      fileType = 'yaml';
    } else if (ext === '.xml') {
      // 基础 XML 支持，可以根据需要扩展
      data = content;
      fileType = 'xml';
    } else {
      // 尝试解析为 JSON
      try {
        data = JSON.parse(content);
        fileType = 'json';
      } catch {
        data = content;
        fileType = 'text';
      }
    }

    return { success: true, data, fileType };
  } catch (error) {
    return { 
      success: false, 
      error: `文件解析错误: ${error.message}`,
      fileType: 'unknown'
    };
  }
}

/**
 * 验证写入参数
 */
function validateWriteParams(filePath, data, operation) {
  if (!filePath) {
    return { success: false, message: '缺少文件路径参数' };
  }

  if (data === undefined || data === null) {
    return { success: false, message: '缺少数据参数' };
  }

  const validOperations = ['overwrite', 'merge', 'append', 'update'];
  if (!validOperations.includes(operation)) {
    return { 
      success: false, 
      message: `无效的操作类型，支持: ${validOperations.join(', ')}` 
    };
  }

  return { success: true };
}

/**
 * 确定文件格式
 */
function determineFileFormat(format, ext) {
  if (format) return format.toLowerCase();
  
  if (ext === '.json') return 'json';
  if (['.yml', '.yaml'].includes(ext)) return 'yaml';
  if (ext === '.xml') return 'xml';
  
  return 'json'; // 默认格式
}

/**
 * 检查文件是否存在
 */
async function checkFileExists(filePath) {
  try {
    await fs.access(filePath);
    return true;
  } catch {
    return false;
  }
}

/**
 * 处理文件操作
 */
async function processFileOperation(filePath, data, operation, fileFormat, encoding, updatePath) {
  try {
    const existingContent = await fs.readFile(filePath, encoding);
    let existingData;
    
    if (fileFormat === 'json') {
      existingData = JSON.parse(existingContent);
    } else if (fileFormat === 'yaml') {
      existingData = yaml.parse(existingContent);
    } else {
      existingData = existingContent;
    }

    let finalData;
    
    switch (operation) {
      case 'merge':
        if (isObject(existingData) && isObject(data)) {
          finalData = deepMerge(existingData, data);
        } else {
          finalData = data;
        }
        break;
        
      case 'append':
        if (Array.isArray(existingData)) {
          finalData = existingData.concat(Array.isArray(data) ? data : [data]);
        } else {
          return { success: false, message: 'append操作仅支持数组' };
        }
        break;
        
      case 'update':
        if (updatePath && isObject(existingData)) {
          finalData = updateNestedValue(existingData, updatePath, data);
        } else {
          finalData = data;
        }
        break;
        
      default:
        finalData = data;
    }

    return { success: true, data: finalData };
  } catch (error) {
    return { 
      success: false, 
      message: '现有文件处理错误',
      error: error.message 
    };
  }
}

/**
 * 验证数据格式
 */
function validateData(data, fileFormat) {
  try {
    if (fileFormat === 'json') {
      JSON.stringify(data);
    } else if (fileFormat === 'yaml') {
      yaml.stringify(data);
    }
    return { success: true };
  } catch (error) {
    return { 
      success: false, 
      message: '数据格式验证失败',
      error: error.message 
    };
  }
}

/**
 * 创建备份文件
 */
async function createBackup(filePath) {
  const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
  const backupPath = `${filePath}.backup.${timestamp}`;
  await fs.copyFile(filePath, backupPath);
  return backupPath;
}

/**
 * 格式化文件内容
 */
function formatContent(data, fileFormat, options = {}) {
  switch (fileFormat) {
    case 'json':
      const indent = options.indent || 2;
      return JSON.stringify(data, null, indent);
      
    case 'yaml':
      const yamlOptions = {
        indent: options.indent || 2,
        lineWidth: options.lineWidth || 80,
        ...options
      };
      return yaml.stringify(data, yamlOptions);
      
    case 'xml':
      // 基础 XML 格式化，可根据需要扩展
      return typeof data === 'string' ? data : JSON.stringify(data);
      
    default:
      return typeof data === 'string' ? data : JSON.stringify(data, null, 2);
  }
}

/**
 * 原子写入
 */
async function atomicWrite(filePath, content, encoding) {
  const tempPath = `${filePath}.tmp.${Date.now()}`;
  try {
    await fs.writeFile(tempPath, content, encoding);
    await fs.rename(tempPath, filePath);
  } catch (error) {
    // 清理临时文件
    try {
      await fs.unlink(tempPath);
    } catch {}
    throw error;
  }
}

/**
 * 列出文件
 */
async function listFiles(dirPath, filter, recursive = false, includeMetadata = false) {
  const files = [];
  const filterRegex = filter ? new RegExp(filter, 'i') : null;

  async function scan(currentPath, relativePath = '') {
    try {
      const entries = await fs.readdir(currentPath, { withFileTypes: true });
      
      for (const entry of entries) {
        const fullPath = path.join(currentPath, entry.name);
        const relPath = path.join(relativePath, entry.name);
        
        if (entry.isFile()) {
          if (!filterRegex || filterRegex.test(entry.name)) {
            const fileInfo = {
              name: entry.name,
              path: fullPath,
              relativePath: relPath,
              type: 'file',
              extension: path.extname(entry.name)
            };
            
            if (includeMetadata) {
              const stats = await fs.stat(fullPath);
              fileInfo.metadata = {
                size: stats.size,
                modified: stats.mtime,
                created: stats.birthtime
              };
            }
            
            files.push(fileInfo);
          }
        } else if (entry.isDirectory() && recursive) {
          await scan(fullPath, relPath);
        }
      }
    } catch (error) {
      logger.warn(`[Data Editor API] 扫描目录失败: ${currentPath}`, error);
    }
  }

  await scan(dirPath);
  return files;
}

/**
 * 深度合并对象
 */
function deepMerge(target, source) {
  const output = { ...target };
  
  if (isObject(target) && isObject(source)) {
    Object.keys(source).forEach(key => {
      if (isObject(source[key])) {
        if (!(key in target)) {
          output[key] = source[key];
        } else {
          output[key] = deepMerge(target[key], source[key]);
        }
      } else {
        output[key] = source[key];
      }
    });
  }
  
  return output;
}

/**
 * 判断是否为对象
 */
function isObject(item) {
  return item && typeof item === 'object' && !Array.isArray(item);
}

/**
 * 更新嵌套对象的值
 */
function updateNestedValue(obj, path, value) {
  const keys = path.split('.');
  const result = JSON.parse(JSON.stringify(obj));
  let current = result;
  
  for (let i = 0; i < keys.length - 1; i++) {
    const key = keys[i];
    if (!current[key] || typeof current[key] !== 'object') {
      current[key] = {};
    }
    current = current[key];
  }
  
  current[keys[keys.length - 1]] = value;
  return result;
}